package com.bzkj.basicinfo.service.impl;

import com.bzkj.basicinfo.domain.CustomerMapping;
import com.bzkj.basicinfo.domain.vo.AutoMatchResultVo;
import com.bzkj.basicinfo.domain.vo.CustomerComparisonVo;
import com.bzkj.basicinfo.domain.warehouse.PdaMsfxCustomer;
import com.bzkj.basicinfo.domain.yxl.Customer;
import com.bzkj.basicinfo.mapper.CustomerMappingMapper;
import com.bzkj.basicinfo.mapper.PdaMsfxCustomerMapper;
import com.bzkj.basicinfo.mapper.YxlCustomerMapper;
import com.bzkj.basicinfo.service.CustomerComparisonService;
import com.bzkj.basicinfo.service.CustomerMappingService;
import com.bzkj.common.annotation.DataSource;
import com.bzkj.common.core.domain.AjaxResult;
import com.bzkj.common.enums.DataSourceType;
import com.bzkj.framework.datasource.DynamicDataSourceContextHolder;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 往来单位对比服务实现类
 * 
 * @author system
 * @date 2025-01-29
 */
@Service
public class CustomerComparisonServiceImpl implements CustomerComparisonService {

    private static final Logger logger = LoggerFactory.getLogger(CustomerComparisonServiceImpl.class);

    @Autowired
    private PdaMsfxCustomerMapper pdaMsfxCustomerMapper;

    @Autowired
    private YxlCustomerMapper yxlCustomerMapper;

    @Autowired
    private CustomerMappingMapper customerMappingMapper;

    @Autowired
    private CustomerMappingService customerMappingService;

    // 自注入，用于调用带有@DataSource注解的方法
    @Autowired
    private CustomerComparisonService self;
    
    /**
     * 查询码上放心往来单位列表（包含映射状态）
     */
    @Override
    public CustomerComparisonVo.MsfxCustomerVo[] selectMsfxCustomerList(String customerName, Boolean mappingStatus) {
        // 先查询码上放心客户数据
        List<PdaMsfxCustomer> customers = getMsfxCustomers(customerName);

        // 提取客户ID列表
        List<String> customerIds = customers.stream()
            .map(PdaMsfxCustomer::getCustomerId)
            .filter(Objects::nonNull)
            .collect(Collectors.toList());

        // 再查询映射关系数据（只查询当前客户列表对应的映射关系）
        Map<String, CustomerMapping> mappingMap = getMsfxMappingMap(customerIds);

        List<CustomerComparisonVo.MsfxCustomerVo> result = new ArrayList<>();

        for (PdaMsfxCustomer customer : customers) {
            CustomerComparisonVo.MsfxCustomerVo vo = new CustomerComparisonVo.MsfxCustomerVo();
            BeanUtils.copyProperties(customer, vo);

            // 设置映射状态
            CustomerMapping mapping = mappingMap.get(customer.getCustomerId());
            vo.setIsMapped(mapping != null);
            if (mapping != null) {
                vo.setMappedErpCode(mapping.getErpCustomerCode());
                vo.setMappedErpName(mapping.getErpCustomerName());
                vo.setMappingId(mapping.getId());
            }

            // 根据映射状态过滤
            if (mappingStatus == null || Objects.equals(mappingStatus, vo.getIsMapped())) {
                result.add(vo);
            }
        }

        return result.toArray(new CustomerComparisonVo.MsfxCustomerVo[0]);
    }

    /**
     * 分页查询码上放心往来单位列表（包含映射状态）
     */
    @Override
    public PageInfo<CustomerComparisonVo.MsfxCustomerVo> selectMsfxCustomerListWithPage(String customerName, Boolean mappingStatus, int pageNum, int pageSize) {
        if (mappingStatus == null) {
            // 如果不需要按映射状态过滤，使用原有的高效分页逻辑
            return selectMsfxCustomerListWithPageOriginal(customerName, pageNum, pageSize);
        } else {
            // 如果需要按映射状态过滤，使用新的过滤分页逻辑
            return selectMsfxCustomerListWithPageFiltered(customerName, mappingStatus, pageNum, pageSize);
        }
    }

    /**
     * 原有的分页查询逻辑（不按映射状态过滤）
     */
    private PageInfo<CustomerComparisonVo.MsfxCustomerVo> selectMsfxCustomerListWithPageOriginal(String customerName, int pageNum, int pageSize) {
        // 设置分页参数
        PageHelper.startPage(pageNum, pageSize);

        // 先查询码上放心客户数据（这里会应用分页）
        List<PdaMsfxCustomer> customers = getMsfxCustomers(customerName);

        // 获取分页信息（必须在下一个查询之前获取）
        PageInfo<PdaMsfxCustomer> pageInfo = new PageInfo<>(customers);

        // 提取客户ID列表
        List<String> customerIds = customers.stream()
            .map(PdaMsfxCustomer::getCustomerId)
            .filter(Objects::nonNull)
            .collect(Collectors.toList());

        // 查询映射关系数据（这个查询不会影响分页信息，因为我们已经获取了PageInfo）
        Map<String, CustomerMapping> mappingMap = getMsfxMappingMap(customerIds);

        List<CustomerComparisonVo.MsfxCustomerVo> result = new ArrayList<>();

        for (PdaMsfxCustomer customer : customers) {
            CustomerComparisonVo.MsfxCustomerVo vo = new CustomerComparisonVo.MsfxCustomerVo();
            BeanUtils.copyProperties(customer, vo);

            // 设置映射状态
            CustomerMapping mapping = mappingMap.get(customer.getCustomerId());
            vo.setIsMapped(mapping != null);
            if (mapping != null) {
                vo.setMappedErpCode(mapping.getErpCustomerCode());
                vo.setMappedErpName(mapping.getErpCustomerName());
                vo.setMappingId(mapping.getId());
                logger.debug("码上放心客户 {} (customerId: {}) 找到映射关系: {}", customer.getCustomerName(), customer.getCustomerId(), mapping.getId());
            } else {
                logger.debug("码上放心客户 {} (customerId: {}) 未找到映射关系", customer.getCustomerName(), customer.getCustomerId());
            }

            result.add(vo);
        }

        // 创建新的PageInfo，保持原有的分页信息
        PageInfo<CustomerComparisonVo.MsfxCustomerVo> resultPageInfo = new PageInfo<>(result);
        resultPageInfo.setTotal(pageInfo.getTotal());
        resultPageInfo.setPages(pageInfo.getPages());
        resultPageInfo.setPageNum(pageInfo.getPageNum());
        resultPageInfo.setPageSize(pageInfo.getPageSize());
        resultPageInfo.setSize(pageInfo.getSize());
        resultPageInfo.setStartRow(pageInfo.getStartRow());
        resultPageInfo.setEndRow(pageInfo.getEndRow());
        resultPageInfo.setPrePage(pageInfo.getPrePage());
        resultPageInfo.setNextPage(pageInfo.getNextPage());
        resultPageInfo.setIsFirstPage(pageInfo.isIsFirstPage());
        resultPageInfo.setIsLastPage(pageInfo.isIsLastPage());
        resultPageInfo.setHasPreviousPage(pageInfo.isHasPreviousPage());
        resultPageInfo.setHasNextPage(pageInfo.isHasNextPage());
        resultPageInfo.setNavigatePages(pageInfo.getNavigatePages());
        resultPageInfo.setNavigatepageNums(pageInfo.getNavigatepageNums());
        resultPageInfo.setNavigateFirstPage(pageInfo.getNavigateFirstPage());
        resultPageInfo.setNavigateLastPage(pageInfo.getNavigateLastPage());

        return resultPageInfo;
    }

    /**
     * 按映射状态过滤的分页查询逻辑
     */
    private PageInfo<CustomerComparisonVo.MsfxCustomerVo> selectMsfxCustomerListWithPageFiltered(String customerName, Boolean mappingStatus, int pageNum, int pageSize) {
        logger.info("执行按映射状态过滤的分页查询，mappingStatus: {}", mappingStatus);

        // 1. 查询所有符合条件的客户（不分页）
        List<PdaMsfxCustomer> allCustomers = getMsfxCustomers(customerName);
        logger.info("查询到符合名称条件的客户总数: {}", allCustomers.size());

        // 2. 获取映射关系（支持一对多）
        List<String> customerIds = allCustomers.stream()
            .map(PdaMsfxCustomer::getCustomerId)
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
        Map<String, List<CustomerMapping>> mappingMapMultiple = getMsfxMappingMapMultiple(customerIds);

        // 3. 过滤出符合映射状态的客户
        List<CustomerComparisonVo.MsfxCustomerVo> filteredResult = new ArrayList<>();
        for (PdaMsfxCustomer customer : allCustomers) {
            CustomerComparisonVo.MsfxCustomerVo vo = new CustomerComparisonVo.MsfxCustomerVo();
            BeanUtils.copyProperties(customer, vo);

            // 设置映射状态（支持一对多）
            List<CustomerMapping> mappings = mappingMapMultiple.get(customer.getCustomerId());
            boolean isMapped = mappings != null && !mappings.isEmpty();
            vo.setIsMapped(isMapped);

            if (isMapped) {
                // 设置映射数量
                vo.setMappingCount(mappings.size());

                // 为了兼容性，设置第一个映射关系的信息
                CustomerMapping firstMapping = mappings.get(0);
                vo.setMappedErpCode(firstMapping.getErpCustomerCode());
                vo.setMappedErpName(firstMapping.getErpCustomerName());
                vo.setMappingId(firstMapping.getId());

                // 设置所有映射关系列表
                List<CustomerComparisonVo.MappingInfo> mappingInfoList = mappings.stream()
                    .map(mapping -> {
                        CustomerComparisonVo.MappingInfo info = new CustomerComparisonVo.MappingInfo();
                        info.setMappingId(mapping.getId());
                        info.setErpCustomerCode(mapping.getErpCustomerCode());
                        info.setErpCustomerName(mapping.getErpCustomerName());
                        info.setErpDanwbh(mapping.getErpDanwbh());
                        info.setMappingType(mapping.getMappingType());
                        info.setCreateTime(mapping.getCreateTime());
                        return info;
                    })
                    .collect(Collectors.toList());
                vo.setMappingList(mappingInfoList);
            } else {
                vo.setMappingCount(0);
                vo.setMappingList(new ArrayList<>());
            }

            // 根据映射状态过滤
            if (Objects.equals(mappingStatus, vo.getIsMapped())) {
                filteredResult.add(vo);
            }
        }

        logger.info("过滤后符合映射状态的客户数量: {}", filteredResult.size());

        // 4. 手动分页
        int total = filteredResult.size();
        int startIndex = (pageNum - 1) * pageSize;
        int endIndex = Math.min(startIndex + pageSize, total);

        List<CustomerComparisonVo.MsfxCustomerVo> pageData = new ArrayList<>();
        if (startIndex < total) {
            pageData = filteredResult.subList(startIndex, endIndex);
        }

        // 5. 构建分页信息
        PageInfo<CustomerComparisonVo.MsfxCustomerVo> pageInfo = new PageInfo<>(pageData);
        pageInfo.setTotal(total);
        pageInfo.setPageNum(pageNum);
        pageInfo.setPageSize(pageSize);
        pageInfo.setPages((int) Math.ceil((double) total / pageSize));
        pageInfo.setSize(pageData.size());
        pageInfo.setStartRow(startIndex + 1);
        pageInfo.setEndRow(startIndex + pageData.size());
        pageInfo.setIsFirstPage(pageNum == 1);
        pageInfo.setIsLastPage(pageNum >= pageInfo.getPages());
        pageInfo.setHasPreviousPage(pageNum > 1);
        pageInfo.setHasNextPage(pageNum < pageInfo.getPages());

        return pageInfo;
    }

    /**
     * 查询码上放心客户数据
     */
    @DataSource(DataSourceType.MASTER)
    private List<PdaMsfxCustomer> getMsfxCustomers(String customerName) {
        PdaMsfxCustomer queryParam = new PdaMsfxCustomer();
        if (customerName != null && !customerName.trim().isEmpty()) {
            queryParam.setCustomerName(customerName);
        }
        return pdaMsfxCustomerMapper.selectPdaMsfxCustomerList(queryParam);
    }

    /**
     * 获取码上放心客户映射关系Map
     */
    @DataSource(DataSourceType.MASTER)
    private Map<String, CustomerMapping> getMsfxMappingMap() {
        List<String> mappedIds = customerMappingMapper.selectMappedMsfxCustomerIds();
        return mappedIds.stream()
            .collect(Collectors.toMap(
                id -> id,
                id -> customerMappingMapper.selectByMsfxCustomerId(id)
            ));
    }

    /**
     * 根据客户ID列表获取码上放心客户映射关系Map（支持大量数据分批查询）
     * 修改为支持一对多关系，返回Map<String, List<CustomerMapping>>
     */
    @DataSource(DataSourceType.MASTER)
    private Map<String, List<CustomerMapping>> getMsfxMappingMapMultiple(List<String> customerIds) {
        if (customerIds == null || customerIds.isEmpty()) {
            return new HashMap<>();
        }

        // 如果数据量小于2000，直接查询
        if (customerIds.size() <= 2000) {
            List<CustomerMapping> mappings = customerMappingMapper.selectMappingsByMsfxCustomerIds(customerIds);
            return mappings.stream()
                .collect(Collectors.groupingBy(CustomerMapping::getMsfxCustomerId));
        }

        // 如果数据量大于2000，分批查询
        logger.info("客户ID数量过多({}个)，开始分批查询映射关系", customerIds.size());
        Map<String, List<CustomerMapping>> result = new HashMap<>();
        int batchSize = 2000;

        for (int i = 0; i < customerIds.size(); i += batchSize) {
            int endIndex = Math.min(i + batchSize, customerIds.size());
            List<String> batch = customerIds.subList(i, endIndex);

            logger.debug("查询第{}批映射关系，范围：{}-{}", (i / batchSize + 1), i, endIndex - 1);
            List<CustomerMapping> batchMappings = customerMappingMapper.selectMappingsByMsfxCustomerIds(batch);

            Map<String, List<CustomerMapping>> batchResult = batchMappings.stream()
                .collect(Collectors.groupingBy(CustomerMapping::getMsfxCustomerId));

            batchResult.forEach((customerId, mappings) ->
                result.computeIfAbsent(customerId, k -> new ArrayList<>()).addAll(mappings)
            );
        }

        logger.info("分批查询完成，共查询到{}个客户的映射关系", result.size());
        return result;
    }

    /**
     * 根据客户ID列表获取码上放心客户映射关系Map（兼容旧版本，返回第一个映射关系）
     */
    @DataSource(DataSourceType.MASTER)
    private Map<String, CustomerMapping> getMsfxMappingMap(List<String> customerIds) {
        Map<String, List<CustomerMapping>> multipleMap = getMsfxMappingMapMultiple(customerIds);
        return multipleMap.entrySet().stream()
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                entry -> entry.getValue().get(0) // 取第一个映射关系，保持兼容性
            ));
    }
    
    /**
     * 查询ERP往来单位列表（包含映射状态）
     */
    @Override
    public CustomerComparisonVo.ErpCustomerVo[] selectErpCustomerList(String dwmch, Boolean mappingStatus) {
        logger.info("开始查询ERP客户列表，参数：dwmch={}, mappingStatus={}", dwmch, mappingStatus);
        logger.info("当前数据源：{}", DynamicDataSourceContextHolder.getDataSourceType());

        List<Customer> customers;
        Map<String, CustomerMapping> mappingMap;

        try {
            // 方案1：使用自注入调用（推荐）
            customers = self.getErpCustomersFromSlave(dwmch);
            logger.info("从从库查询到客户数量：{}", customers.size());

            // 提取客户编码列表
            List<String> erpCustomerCodes = customers.stream()
                .map(Customer::getDanwbh)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

            mappingMap = getErpMappingMapFromMaster(erpCustomerCodes);
            logger.info("从主库查询到映射关系数量：{}", mappingMap.size());
        } catch (Exception e) {
            logger.error("自注入方式调用失败，尝试手动切换数据源", e);

            // 方案2：手动切换数据源（备用方案）
            try {
                DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.SLAVE.name());
                logger.info("手动切换到从库，当前数据源：{}", DynamicDataSourceContextHolder.getDataSourceType());
                customers = getErpCustomersDirectly(dwmch);
                logger.info("从从库查询到客户数量：{}", customers.size());
            } finally {
                DynamicDataSourceContextHolder.clearDataSourceType();
            }

            // 提取客户编码列表
            List<String> erpCustomerCodes = customers.stream()
                .map(Customer::getDanwbh)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

            try {
                DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
                logger.info("手动切换到主库，当前数据源：{}", DynamicDataSourceContextHolder.getDataSourceType());
                mappingMap = getErpMappingMapDirectly(erpCustomerCodes);
                logger.info("从主库查询到映射关系数量：{}", mappingMap.size());
            } finally {
                DynamicDataSourceContextHolder.clearDataSourceType();
            }
        }

        List<CustomerComparisonVo.ErpCustomerVo> result = new ArrayList<>();

        for (Customer customer : customers) {
            CustomerComparisonVo.ErpCustomerVo vo = new CustomerComparisonVo.ErpCustomerVo();
            BeanUtils.copyProperties(customer, vo);

            // 设置映射状态
            CustomerMapping mapping = mappingMap.get(customer.getDanwbh());
            vo.setIsMapped(mapping != null);
            if (mapping != null) {
                vo.setMappedMsfxId(mapping.getMsfxCustomerId());
                vo.setMappedMsfxName(mapping.getMsfxCustomerName());
                vo.setMappingId(mapping.getId());
            }

            // 根据映射状态过滤
            if (mappingStatus == null || Objects.equals(mappingStatus, vo.getIsMapped())) {
                result.add(vo);
            }
        }

        return result.toArray(new CustomerComparisonVo.ErpCustomerVo[0]);
    }

    /**
     * 分页查询ERP往来单位列表（包含映射状态）
     */
    @Override
    public PageInfo<CustomerComparisonVo.ErpCustomerVo> selectErpCustomerListWithPage(String dwmch, Boolean mappingStatus, int pageNum, int pageSize) {
        logger.info("开始分页查询ERP客户列表，参数：dwmch={}, mappingStatus={}, pageNum={}, pageSize={}", dwmch, mappingStatus, pageNum, pageSize);

        if (mappingStatus == null) {
            // 如果不需要按映射状态过滤，使用原有的高效分页逻辑
            return selectErpCustomerListWithPageOriginal(dwmch, pageNum, pageSize);
        } else {
            // 如果需要按映射状态过滤，使用新的过滤分页逻辑
            return selectErpCustomerListWithPageFiltered(dwmch, mappingStatus, pageNum, pageSize);
        }
    }

    /**
     * 原有的ERP客户分页查询逻辑（不按映射状态过滤）
     */
    private PageInfo<CustomerComparisonVo.ErpCustomerVo> selectErpCustomerListWithPageOriginal(String dwmch, int pageNum, int pageSize) {

        List<Customer> customers;
        PageInfo<Customer> pageInfo;
        Map<String, CustomerMapping> mappingMap;

        try {
            // 设置分页参数
            PageHelper.startPage(pageNum, pageSize);

            // 方案1：使用自注入调用（推荐）
            customers = self.getErpCustomersFromSlave(dwmch);
            logger.info("从从库查询到客户数量：{}", customers.size());

            // 获取分页信息（必须在下一个查询之前获取）
            pageInfo = new PageInfo<>(customers);

            // 提取客户编码列表
            List<String> erpCustomerCodes = customers.stream()
                .map(Customer::getDanwbh)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

            mappingMap = getErpMappingMapFromMaster(erpCustomerCodes);
            logger.info("从主库查询到映射关系数量：{}", mappingMap.size());
        } catch (Exception e) {
            logger.error("自注入方式调用失败，尝试手动切换数据源", e);

            // 方案2：手动切换数据源（备用方案）
            try {
                PageHelper.startPage(pageNum, pageSize);
                DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.SLAVE.name());
                logger.info("手动切换到从库，当前数据源：{}", DynamicDataSourceContextHolder.getDataSourceType());
                customers = getErpCustomersDirectly(dwmch);
                logger.info("从从库查询到客户数量：{}", customers.size());

                // 获取分页信息
                pageInfo = new PageInfo<>(customers);
            } finally {
                DynamicDataSourceContextHolder.clearDataSourceType();
            }

            // 提取客户编码列表
            List<String> erpCustomerCodes = customers.stream()
                .map(Customer::getDanwbh)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

            try {
                DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
                logger.info("手动切换到主库，当前数据源：{}", DynamicDataSourceContextHolder.getDataSourceType());
                mappingMap = getErpMappingMapDirectly(erpCustomerCodes);
                logger.info("从主库查询到映射关系数量：{}", mappingMap.size());
            } finally {
                DynamicDataSourceContextHolder.clearDataSourceType();
            }
        }

        List<CustomerComparisonVo.ErpCustomerVo> result = new ArrayList<>();

        for (Customer customer : customers) {
            CustomerComparisonVo.ErpCustomerVo vo = new CustomerComparisonVo.ErpCustomerVo();
            BeanUtils.copyProperties(customer, vo);

            // 设置映射状态
            CustomerMapping mapping = mappingMap.get(customer.getDanwbh());
            vo.setIsMapped(mapping != null);
            if (mapping != null) {
                vo.setMappedMsfxId(mapping.getMsfxCustomerId());
                vo.setMappedMsfxName(mapping.getMsfxCustomerName());
                vo.setMappingId(mapping.getId());
                logger.debug("ERP客户 {} (danwbh: {}) 找到映射关系: {}", customer.getDwmch(), customer.getDanwbh(), mapping.getId());
            } else {
                logger.debug("ERP客户 {} (danwbh: {}) 未找到映射关系", customer.getDwmch(), customer.getDanwbh());
            }

            result.add(vo);
        }

        // 创建新的PageInfo，保持原有的分页信息
        PageInfo<CustomerComparisonVo.ErpCustomerVo> resultPageInfo = new PageInfo<>(result);
        resultPageInfo.setTotal(pageInfo.getTotal());
        resultPageInfo.setPages(pageInfo.getPages());
        resultPageInfo.setPageNum(pageInfo.getPageNum());
        resultPageInfo.setPageSize(pageInfo.getPageSize());
        resultPageInfo.setSize(pageInfo.getSize());
        resultPageInfo.setStartRow(pageInfo.getStartRow());
        resultPageInfo.setEndRow(pageInfo.getEndRow());
        resultPageInfo.setPrePage(pageInfo.getPrePage());
        resultPageInfo.setNextPage(pageInfo.getNextPage());
        resultPageInfo.setIsFirstPage(pageInfo.isIsFirstPage());
        resultPageInfo.setIsLastPage(pageInfo.isIsLastPage());
        resultPageInfo.setHasPreviousPage(pageInfo.isHasPreviousPage());
        resultPageInfo.setHasNextPage(pageInfo.isHasNextPage());
        resultPageInfo.setNavigatePages(pageInfo.getNavigatePages());
        resultPageInfo.setNavigatepageNums(pageInfo.getNavigatepageNums());
        resultPageInfo.setNavigateFirstPage(pageInfo.getNavigateFirstPage());
        resultPageInfo.setNavigateLastPage(pageInfo.getNavigateLastPage());

        return resultPageInfo;
    }

    /**
     * 从主库获取ERP客户映射关系Map
     */
    @Override
    @DataSource(DataSourceType.MASTER)
    public Map<String, CustomerMapping> getErpMappingMapFromMaster() {
        logger.info("进入getErpMappingMapFromMaster方法，当前数据源：{}", DynamicDataSourceContextHolder.getDataSourceType());
        List<String> mappedCodes = customerMappingMapper.selectMappedErpCustomerCodes();
        Map<String, CustomerMapping> result = mappedCodes.stream()
            .collect(Collectors.toMap(
                code -> code,
                code -> customerMappingMapper.selectByErpCustomerCode(code)
            ));
        logger.info("getErpMappingMapFromMaster查询结果数量：{}", result.size());
        return result;
    }

    /**
     * 根据ERP客户编码列表从主库获取映射关系Map（支持大量数据分批查询）
     */
    @DataSource(DataSourceType.MASTER)
    private Map<String, CustomerMapping> getErpMappingMapFromMaster(List<String> erpCustomerCodes) {
        logger.info("进入getErpMappingMapFromMaster(List)方法，当前数据源：{}", DynamicDataSourceContextHolder.getDataSourceType());
        if (erpCustomerCodes == null || erpCustomerCodes.isEmpty()) {
            return new HashMap<>();
        }

        // 如果数据量小于2000，直接查询
        if (erpCustomerCodes.size() <= 2000) {
            List<CustomerMapping> mappings = customerMappingMapper.selectMappingsByErpCustomerCodes(erpCustomerCodes);
            Map<String, CustomerMapping> result = mappings.stream()
                .collect(Collectors.toMap(
                    CustomerMapping::getErpCustomerCode,
                    mapping -> mapping
                ));
            logger.info("getErpMappingMapFromMaster(List)查询结果数量：{}", result.size());
            return result;
        }

        // 如果数据量大于2000，分批查询
        logger.info("ERP客户编码数量过多({}个)，开始分批查询映射关系", erpCustomerCodes.size());
        Map<String, CustomerMapping> result = new HashMap<>();
        int batchSize = 2000;

        for (int i = 0; i < erpCustomerCodes.size(); i += batchSize) {
            int endIndex = Math.min(i + batchSize, erpCustomerCodes.size());
            List<String> batch = erpCustomerCodes.subList(i, endIndex);

            logger.debug("查询第{}批ERP映射关系，范围：{}-{}", (i / batchSize + 1), i, endIndex - 1);
            List<CustomerMapping> batchMappings = customerMappingMapper.selectMappingsByErpCustomerCodes(batch);

            batchMappings.forEach(mapping ->
                result.put(mapping.getErpCustomerCode(), mapping)
            );
        }

        logger.info("ERP分批查询完成，共查询到{}个映射关系", result.size());
        return result;
    }

    /**
     * 查询ERP客户数据（从从库查询）
     */
    @Override
    @DataSource(value = DataSourceType.SLAVE)
    public List<Customer> getErpCustomersFromSlave(String dwmch) {
        logger.info("进入getErpCustomersFromSlave方法，当前数据源：{}", DynamicDataSourceContextHolder.getDataSourceType());
        com.bzkj.basicinfo.domain.yxl.CustomerDto queryParam = new com.bzkj.basicinfo.domain.yxl.CustomerDto();
        if (dwmch != null && !dwmch.trim().isEmpty()) {
            queryParam.setDwmch(dwmch);
        }
        List<Customer> result = yxlCustomerMapper.queryEnabledCustomerList(queryParam);
        logger.info("getErpCustomersFromSlave查询结果数量：{}", result.size());
        return result;
    }

    /**
     * 获取ERP客户映射关系Map
     */
    @DataSource(DataSourceType.MASTER)
    public Map<String, CustomerMapping> getErpMappingMap() {
        List<String> mappedCodes = customerMappingMapper.selectMappedErpCustomerCodes();
        return mappedCodes.stream()
            .collect(Collectors.toMap(
                code -> code,
                code -> customerMappingMapper.selectByErpCustomerCode(code)
            ));
    }

    /**
     * 直接查询ERP客户数据（不使用注解）
     */
    private List<Customer> getErpCustomersDirectly(String dwmch) {
        logger.info("进入getErpCustomersDirectly方法，当前数据源：{}", DynamicDataSourceContextHolder.getDataSourceType());
        com.bzkj.basicinfo.domain.yxl.CustomerDto queryParam = new com.bzkj.basicinfo.domain.yxl.CustomerDto();
        if (dwmch != null && !dwmch.trim().isEmpty()) {
            queryParam.setDwmch(dwmch);
        }
        queryParam.setType("1"); // 设置为客户类型
        List<Customer> result = yxlCustomerMapper.queryCustomerList(queryParam);
        logger.info("getErpCustomersDirectly查询结果数量：{}", result.size());
        return result;
    }

    /**
     * 直接获取ERP客户映射关系Map（不使用注解）
     */
    private Map<String, CustomerMapping> getErpMappingMapDirectly() {
        logger.info("进入getErpMappingMapDirectly方法，当前数据源：{}", DynamicDataSourceContextHolder.getDataSourceType());
        List<String> mappedCodes = customerMappingMapper.selectMappedErpCustomerCodes();
        Map<String, CustomerMapping> result = mappedCodes.stream()
            .collect(Collectors.toMap(
                code -> code,
                code -> customerMappingMapper.selectByErpCustomerCode(code)
            ));
        logger.info("getErpMappingMapDirectly查询结果数量：{}", result.size());
        return result;
    }

    /**
     * 根据ERP客户编码列表直接获取映射关系Map（不使用注解，支持大量数据分批查询）
     */
    private Map<String, CustomerMapping> getErpMappingMapDirectly(List<String> erpCustomerCodes) {
        logger.info("进入getErpMappingMapDirectly(List)方法，当前数据源：{}", DynamicDataSourceContextHolder.getDataSourceType());
        if (erpCustomerCodes == null || erpCustomerCodes.isEmpty()) {
            return new HashMap<>();
        }

        // 如果数据量小于2000，直接查询
        if (erpCustomerCodes.size() <= 2000) {
            List<CustomerMapping> mappings = customerMappingMapper.selectMappingsByErpCustomerCodes(erpCustomerCodes);
            Map<String, CustomerMapping> result = mappings.stream()
                .collect(Collectors.toMap(
                    CustomerMapping::getErpCustomerCode,
                    mapping -> mapping
                ));
            logger.info("getErpMappingMapDirectly(List)查询结果数量：{}", result.size());
            return result;
        }

        // 如果数据量大于2000，分批查询
        logger.info("ERP客户编码数量过多({}个)，开始分批查询映射关系", erpCustomerCodes.size());
        Map<String, CustomerMapping> result = new HashMap<>();
        int batchSize = 2000;

        for (int i = 0; i < erpCustomerCodes.size(); i += batchSize) {
            int endIndex = Math.min(i + batchSize, erpCustomerCodes.size());
            List<String> batch = erpCustomerCodes.subList(i, endIndex);

            logger.debug("查询第{}批ERP映射关系，范围：{}-{}", (i / batchSize + 1), i, endIndex - 1);
            List<CustomerMapping> batchMappings = customerMappingMapper.selectMappingsByErpCustomerCodes(batch);

            batchMappings.forEach(mapping ->
                result.put(mapping.getErpCustomerCode(), mapping)
            );
        }

        logger.info("ERP分批查询完成，共查询到{}个映射关系", result.size());
        return result;
    }

    /**
     * 查询往来单位对比数据
     */
    @Override
    public CustomerComparisonVo selectCustomerComparison(String msfxCustomerName, String erpCustomerName, Boolean mappingStatus) {
        CustomerComparisonVo result = new CustomerComparisonVo();

        // 查询码上放心往来单位
        CustomerComparisonVo.MsfxCustomerVo[] msfxCustomers = selectMsfxCustomerList(msfxCustomerName, mappingStatus);
        result.setMsfxCustomers(java.util.Arrays.asList(msfxCustomers));

        // 查询ERP往来单位
        CustomerComparisonVo.ErpCustomerVo[] erpCustomers = selectErpCustomerList(erpCustomerName, mappingStatus);
        result.setErpCustomers(java.util.Arrays.asList(erpCustomers));

        return result;
    }

    /**
     * 查询未映射的码上放心往来单位
     */
    @Override
    public CustomerComparisonVo.MsfxCustomerVo[] selectUnmappedMsfxCustomers(String customerName) {
        return selectMsfxCustomerList(customerName, false);
    }

    /**
     * 查询未映射的ERP往来单位
     */
    @Override
    public CustomerComparisonVo.ErpCustomerVo[] selectUnmappedErpCustomers(String dwmch) {
        return selectErpCustomerList(dwmch, false);
    }

    /**
     * 查询启用状态的ERP往来单位列表（包含映射状态）
     */
    @Override
    public CustomerComparisonVo.ErpCustomerVo[] selectEnabledErpCustomerList(String dwmch, Boolean mappingStatus) {
        logger.info("开始查询启用状态的ERP客户列表，参数：dwmch={}, mappingStatus={}", dwmch, mappingStatus);
        logger.info("当前数据源：{}", DynamicDataSourceContextHolder.getDataSourceType());

        List<Customer> customers;
        Map<String, CustomerMapping> mappingMap;

        try {
            // 方案1：使用自注入调用（推荐）
            customers = self.getEnabledErpCustomersFromSlave(dwmch);
            logger.info("从从库查询到启用状态客户数量：{}", customers.size());

            // 提取客户编码列表
            List<String> erpCustomerCodes = customers.stream()
                .map(Customer::getDanwbh)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

            mappingMap = getErpMappingMapFromMaster(erpCustomerCodes);
            logger.info("从主库查询到映射关系数量：{}", mappingMap.size());
        } catch (Exception e) {
            logger.error("自注入方式调用失败，尝试手动切换数据源", e);

            // 方案2：手动切换数据源（备用方案）
            try {
                DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.SLAVE.name());
                logger.info("手动切换到从库，当前数据源：{}", DynamicDataSourceContextHolder.getDataSourceType());
                customers = getEnabledErpCustomersDirectly(dwmch);
                logger.info("从从库查询到启用状态客户数量：{}", customers.size());
            } finally {
                DynamicDataSourceContextHolder.clearDataSourceType();
            }

            // 提取客户编码列表
            List<String> erpCustomerCodes = customers.stream()
                .map(Customer::getDanwbh)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

            try {
                DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
                logger.info("手动切换到主库，当前数据源：{}", DynamicDataSourceContextHolder.getDataSourceType());
                mappingMap = getErpMappingMapDirectly(erpCustomerCodes);
                logger.info("从主库查询到映射关系数量：{}", mappingMap.size());
            } finally {
                DynamicDataSourceContextHolder.clearDataSourceType();
            }
        }

        List<CustomerComparisonVo.ErpCustomerVo> result = new ArrayList<>();

        for (Customer customer : customers) {
            CustomerComparisonVo.ErpCustomerVo vo = new CustomerComparisonVo.ErpCustomerVo();
            BeanUtils.copyProperties(customer, vo);

            // 设置映射状态
            CustomerMapping mapping = mappingMap.get(customer.getDanwbh());
            vo.setIsMapped(mapping != null);
            if (mapping != null) {
                vo.setMappedMsfxId(mapping.getMsfxCustomerId());
                vo.setMappedMsfxName(mapping.getMsfxCustomerName());
                vo.setMappingId(mapping.getId());
            }

            // 根据映射状态过滤
            if (mappingStatus == null || Objects.equals(mappingStatus, vo.getIsMapped())) {
                result.add(vo);
            }
        }

        return result.toArray(new CustomerComparisonVo.ErpCustomerVo[0]);
    }

    /**
     * 查询启用状态的ERP客户数据（从从库查询）
     */
    @Override
    @DataSource(value = DataSourceType.SLAVE)
    public List<Customer> getEnabledErpCustomersFromSlave(String dwmch) {
        logger.info("进入getEnabledErpCustomersFromSlave方法，当前数据源：{}", DynamicDataSourceContextHolder.getDataSourceType());
        com.bzkj.basicinfo.domain.yxl.CustomerDto queryParam = new com.bzkj.basicinfo.domain.yxl.CustomerDto();
        if (dwmch != null && !dwmch.trim().isEmpty()) {
            queryParam.setDwmch(dwmch);
        }
        queryParam.setType("1"); // 设置为客户类型
        List<Customer> result = yxlCustomerMapper.queryEnabledCustomerList(queryParam);
        logger.info("getEnabledErpCustomersFromSlave查询结果数量：{}", result.size());
        return result;
    }

    /**
     * 直接查询启用状态的ERP客户数据（不使用注解）
     */
    private List<Customer> getEnabledErpCustomersDirectly(String dwmch) {
        logger.info("进入getEnabledErpCustomersDirectly方法，当前数据源：{}", DynamicDataSourceContextHolder.getDataSourceType());
        com.bzkj.basicinfo.domain.yxl.CustomerDto queryParam = new com.bzkj.basicinfo.domain.yxl.CustomerDto();
        if (dwmch != null && !dwmch.trim().isEmpty()) {
            queryParam.setDwmch(dwmch);
        }
        queryParam.setType("1"); // 设置为客户类型
        List<Customer> result = yxlCustomerMapper.queryEnabledCustomerList(queryParam);
        logger.info("getEnabledErpCustomersDirectly查询结果数量：{}", result.size());
        return result;
    }

    /**
     * 预览基于名称完全匹配的自动映射结果
     */
    @Override
    public AjaxResult previewAutoMatch() {
        logger.info("开始预览自动匹配结果");

        try {
            AutoMatchResultVo result = performAutoMatch(true);
            logger.info("预览完成，匹配成功数量：{}", result.getSuccessCount());
            return AjaxResult.success("预览成功", result);
        } catch (Exception e) {
            logger.error("预览自动匹配失败", e);
            return AjaxResult.error("预览失败：" + e.getMessage());
        }
    }

    /**
     * 基于名称完全匹配自动创建映射关系
     */
    @Override
    public AjaxResult autoMatchByName() {
        logger.info("开始执行自动匹配");

        try {
            AutoMatchResultVo result = performAutoMatch(false);
            logger.info("自动匹配完成，成功创建映射关系数量：{}", result.getSuccessCount());
            return AjaxResult.success("自动匹配完成", result);
        } catch (Exception e) {
            logger.error("自动匹配失败", e);
            return AjaxResult.error("自动匹配失败：" + e.getMessage());
        }
    }

    /**
     * 执行自动匹配的核心逻辑
     *
     * @param previewOnly 是否仅预览，不实际创建映射关系
     * @return 匹配结果
     */
    private AutoMatchResultVo performAutoMatch(boolean previewOnly) {
        logger.info("执行自动匹配，预览模式：{}", previewOnly);

        // 1. 获取所有未映射的码上放心客户（优化：使用直接查询避免参数过多）
        CustomerComparisonVo.MsfxCustomerVo[] unmappedMsfxCustomers = selectUnmappedMsfxCustomersOptimized();
        logger.info("未映射的码上放心客户数量：{}", unmappedMsfxCustomers.length);

        // 2. 获取所有未映射的ERP客户（优化：使用直接查询避免参数过多）
        CustomerComparisonVo.ErpCustomerVo[] unmappedErpCustomers = selectUnmappedErpCustomersOptimized();
        logger.info("未映射的ERP客户数量：{}", unmappedErpCustomers.length);

        // 3. 创建ERP客户名称到客户对象的映射
        Map<String, CustomerComparisonVo.ErpCustomerVo> erpCustomerMap = java.util.Arrays.stream(unmappedErpCustomers)
            .collect(Collectors.toMap(
                customer -> customer.getDwmch() != null ? customer.getDwmch().trim() : "",
                customer -> customer,
                (existing, replacement) -> {
                    logger.warn("发现重复的ERP客户名称：{}，保留第一个", existing.getDwmch());
                    return existing;
                }
            ));

        // 4. 执行匹配
        List<AutoMatchResultVo.MatchPair> matchPairs = new ArrayList<>();
        int successCount = 0;

        for (CustomerComparisonVo.MsfxCustomerVo msfxCustomer : unmappedMsfxCustomers) {
            String msfxName = msfxCustomer.getCustomerName();
            if (msfxName == null || msfxName.trim().isEmpty()) {
                continue;
            }

            String trimmedMsfxName = msfxName.trim();
            CustomerComparisonVo.ErpCustomerVo matchedErpCustomer = erpCustomerMap.get(trimmedMsfxName);

            if (matchedErpCustomer != null) {
                // 找到匹配的客户
                AutoMatchResultVo.MatchPair matchPair = new AutoMatchResultVo.MatchPair();
                matchPair.setMsfxCustomerId(msfxCustomer.getCustomerId());
                matchPair.setMsfxCustomerName(msfxCustomer.getCustomerName());
                matchPair.setMsfxEntId(msfxCustomer.getCustomerRefEntId());
                matchPair.setErpCustomerCode(matchedErpCustomer.getDanwbh());
                matchPair.setErpCustomerName(matchedErpCustomer.getDwmch());
                matchPair.setErpDanwbh(matchedErpCustomer.getDanwbh());

                matchPairs.add(matchPair);
                successCount++;

                // 如果不是预览模式，创建实际的映射关系
                if (!previewOnly) {
                    createMappingRelation(matchPair);
                }

                logger.debug("匹配成功：{} <-> {}", msfxName, matchedErpCustomer.getDwmch());
            }
        }

        // 5. 构建结果
        AutoMatchResultVo result = new AutoMatchResultVo();
        result.setSuccessCount(successCount);
        result.setTotalMsfxCount(unmappedMsfxCustomers.length);
        result.setTotalErpCount(unmappedErpCustomers.length);
        result.setMsfxOnlyCount(unmappedMsfxCustomers.length - successCount);
        result.setErpOnlyCount(unmappedErpCustomers.length - successCount);
        result.setMatchPairs(matchPairs);

        return result;
    }

    /**
     * 创建映射关系
     *
     * @param matchPair 匹配对信息
     */
    private void createMappingRelation(AutoMatchResultVo.MatchPair matchPair) {
        try {
            AjaxResult result = customerMappingService.createMapping(
                matchPair.getMsfxCustomerId(),
                matchPair.getMsfxCustomerName(),
                matchPair.getMsfxEntId(),
                matchPair.getErpCustomerCode(),
                matchPair.getErpCustomerName(),
                matchPair.getErpDanwbh(),
                "自动匹配创建"
            );

            if (!result.isSuccess()) {
                logger.error("创建映射关系失败：{} <-> {}，错误信息：{}",
                    matchPair.getMsfxCustomerName(),
                    matchPair.getErpCustomerName(),
                    result.get(AjaxResult.MSG_TAG));
            } else {
                logger.info("成功创建映射关系：{} <-> {}",
                    matchPair.getMsfxCustomerName(),
                    matchPair.getErpCustomerName());
            }
        } catch (Exception e) {
            logger.error("创建映射关系异常：{} <-> {}，异常信息：{}",
                matchPair.getMsfxCustomerName(),
                matchPair.getErpCustomerName(),
                e.getMessage(), e);
        }
    }

    /**
     * 优化的查询未映射的码上放心客户（避免参数过多问题）
     */
    private CustomerComparisonVo.MsfxCustomerVo[] selectUnmappedMsfxCustomersOptimized() {
        try {
            // 直接查询所有码上放心客户
            List<PdaMsfxCustomer> allCustomers = pdaMsfxCustomerMapper.selectPdaMsfxCustomerList(new PdaMsfxCustomer());
            logger.info("查询到所有码上放心客户数量：{}", allCustomers.size());

            // 获取所有已映射的客户ID（使用简单查询）
            Set<String> mappedCustomerIds = customerMappingMapper.selectMappedMsfxCustomerIds().stream()
                .collect(Collectors.toSet());
            logger.info("已映射的码上放心客户数量：{}", mappedCustomerIds.size());

            // 过滤出未映射的客户
            List<CustomerComparisonVo.MsfxCustomerVo> result = new ArrayList<>();
            for (PdaMsfxCustomer customer : allCustomers) {
                if (!mappedCustomerIds.contains(customer.getCustomerId())) {
                    CustomerComparisonVo.MsfxCustomerVo vo = new CustomerComparisonVo.MsfxCustomerVo();
                    BeanUtils.copyProperties(customer, vo);
                    vo.setIsMapped(false);
                    result.add(vo);
                }
            }

            logger.info("未映射的码上放心客户数量：{}", result.size());
            return result.toArray(new CustomerComparisonVo.MsfxCustomerVo[0]);
        } catch (Exception e) {
            logger.error("查询未映射的码上放心客户失败", e);
            return new CustomerComparisonVo.MsfxCustomerVo[0];
        }
    }

    /**
     * 优化的查询未映射的ERP客户（避免参数过多问题）
     */
    private CustomerComparisonVo.ErpCustomerVo[] selectUnmappedErpCustomersOptimized() {
        try {
            // 直接查询所有ERP客户
            List<Customer> allCustomers = self.getErpCustomersFromSlave(null);
            logger.info("查询到所有ERP客户数量：{}", allCustomers.size());

            // 获取所有已映射的客户编码（使用简单查询）
            Set<String> mappedCustomerCodes = customerMappingMapper.selectMappedErpCustomerCodes().stream()
                .collect(Collectors.toSet());
            logger.info("已映射的ERP客户数量：{}", mappedCustomerCodes.size());

            // 过滤出未映射的客户
            List<CustomerComparisonVo.ErpCustomerVo> result = new ArrayList<>();
            for (Customer customer : allCustomers) {
                if (!mappedCustomerCodes.contains(customer.getDanwbh())) {
                    CustomerComparisonVo.ErpCustomerVo vo = new CustomerComparisonVo.ErpCustomerVo();
                    BeanUtils.copyProperties(customer, vo);
                    vo.setIsMapped(false);
                    result.add(vo);
                }
            }

            logger.info("未映射的ERP客户数量：{}", result.size());
            return result.toArray(new CustomerComparisonVo.ErpCustomerVo[0]);
        } catch (Exception e) {
            logger.error("查询未映射的ERP客户失败", e);
            return new CustomerComparisonVo.ErpCustomerVo[0];
        }
    }

    /**
     * 按映射状态过滤的ERP客户分页查询逻辑
     */
    private PageInfo<CustomerComparisonVo.ErpCustomerVo> selectErpCustomerListWithPageFiltered(String dwmch, Boolean mappingStatus, int pageNum, int pageSize) {
        logger.info("执行按映射状态过滤的ERP客户分页查询，mappingStatus: {}", mappingStatus);

        // 1. 查询所有符合条件的ERP客户（不分页）
        List<Customer> allCustomers;
        try {
            allCustomers = self.getErpCustomersFromSlave(dwmch);
        } catch (Exception e) {
            logger.error("从从库查询ERP客户失败，尝试手动切换数据源", e);
            try {
                DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.SLAVE.name());
                allCustomers = getErpCustomersDirectly(dwmch);
            } finally {
                DynamicDataSourceContextHolder.clearDataSourceType();
            }
        }
        logger.info("查询到符合名称条件的ERP客户总数: {}", allCustomers.size());

        // 2. 获取映射关系
        List<String> erpCustomerCodes = allCustomers.stream()
            .map(Customer::getDanwbh)
            .filter(Objects::nonNull)
            .collect(Collectors.toList());

        Map<String, CustomerMapping> mappingMap;
        try {
            mappingMap = getErpMappingMapFromMaster(erpCustomerCodes);
        } catch (Exception e) {
            logger.error("从主库查询映射关系失败，尝试手动切换数据源", e);
            try {
                DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
                mappingMap = getErpMappingMapDirectly(erpCustomerCodes);
            } finally {
                DynamicDataSourceContextHolder.clearDataSourceType();
            }
        }

        // 3. 过滤出符合映射状态的客户
        List<CustomerComparisonVo.ErpCustomerVo> filteredResult = new ArrayList<>();
        for (Customer customer : allCustomers) {
            CustomerComparisonVo.ErpCustomerVo vo = new CustomerComparisonVo.ErpCustomerVo();
            BeanUtils.copyProperties(customer, vo);

            // 设置映射状态
            CustomerMapping mapping = mappingMap.get(customer.getDanwbh());
            vo.setIsMapped(mapping != null);
            if (mapping != null) {
                vo.setMappedMsfxId(mapping.getMsfxCustomerId());
                vo.setMappedMsfxName(mapping.getMsfxCustomerName());
                vo.setMappingId(mapping.getId());
            }

            // 根据映射状态过滤
            if (Objects.equals(mappingStatus, vo.getIsMapped())) {
                filteredResult.add(vo);
            }
        }

        logger.info("过滤后符合映射状态的ERP客户数量: {}", filteredResult.size());

        // 4. 手动分页
        int total = filteredResult.size();
        int startIndex = (pageNum - 1) * pageSize;
        int endIndex = Math.min(startIndex + pageSize, total);

        List<CustomerComparisonVo.ErpCustomerVo> pageData = new ArrayList<>();
        if (startIndex < total) {
            pageData = filteredResult.subList(startIndex, endIndex);
        }

        // 5. 构建分页信息
        PageInfo<CustomerComparisonVo.ErpCustomerVo> pageInfo = new PageInfo<>(pageData);
        pageInfo.setTotal(total);
        pageInfo.setPageNum(pageNum);
        pageInfo.setPageSize(pageSize);
        pageInfo.setPages((int) Math.ceil((double) total / pageSize));
        pageInfo.setSize(pageData.size());
        pageInfo.setStartRow(startIndex + 1);
        pageInfo.setEndRow(startIndex + pageData.size());
        pageInfo.setIsFirstPage(pageNum == 1);
        pageInfo.setIsLastPage(pageNum >= pageInfo.getPages());
        pageInfo.setHasPreviousPage(pageNum > 1);
        pageInfo.setHasNextPage(pageNum < pageInfo.getPages());

        return pageInfo;
    }
}
